#include "tcpServer.h"
#include "logger.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "IpAddressPort.h"
#include "msg.h"

TcpServer::TcpServer(const IpAddressPort& IpAddressAndPort)
{
    m_lfd=socket(AF_INET,SOCK_STREAM,0);
    if(-1==m_lfd)
    {
        LOG_FATAL<<strerror(errno);
    }
    struct sockaddr_in ser;
    ser.sin_family=AF_INET;
    ser.sin_addr.s_addr=inet_addr(IpAddressAndPort.GetIpAddress().c_str());
    ser.sin_port=htons(IpAddressAndPort.GetPort());

    if(-1==bind(m_lfd,(struct sockaddr*)&ser,sizeof(ser)))
    {
        LOG_FATAL<<strerror(errno);
    }

    if(-1==listen(m_lfd,5))
    {
        LOG_FATAL<<strerror(errno);
    }
}
TcpServer::~TcpServer()
{
    if(-1==close(m_lfd))
    {
        LOG_FATAL<<strerror(errno);
    }
}
int TcpServer::SendMsg(int cfd,const std::string& msg)
{
    int numberOfSendByte=send(cfd,msg.c_str(),strlen(msg.c_str()),0);
    if(-1==numberOfSendByte)
    {
        LOG_ERROR<<strerror(errno);
    }
    return numberOfSendByte;
}
Msg TcpServer::RecvMsg(int cfd)
{
    char buff[LARGE_BUF_LEN]={0};
    int numberOfRecvByte=recv(cfd,buff,LARGE_BUF_LEN,0);
    if(-1==numberOfRecvByte)
    {
        LOG_ERROR<<strerror(errno);
    }
    return Msg{buff,numberOfRecvByte};
}
int TcpServer::Accept()
{
    struct sockaddr_in cli;
    socklen_t len=sizeof(cli);
    int cfd=accept(m_lfd,(struct sockaddr*)& cli,&len);
    if(cfd==-1)
    {
        LOG_ERROR<<strerror(errno);
    }
    else
    {
        char clientIpBuff[SMALL_BUF_LEN]={0};
        if(!inet_ntop(AF_INET,&cli.sin_addr,clientIpBuff,SMALL_BUF_LEN))
        {
            LOG_ERROR<<strerror(errno);
        }
        else
        {
            std::string clientIp(clientIpBuff);
            unsigned short clientPort =ntohs(cli.sin_port);
            IpAddressPort ipaddressport(clientIp,clientPort);
            LOG_INFO<<ipaddressport.ToString();
        }
    }
    return cfd;
} 
int TcpServer::GetLfd()const
{
    return m_lfd;
}
